﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GnufExtension.h"
#include "GnufQtObjectPtr.h"
#include <GnufPallet.h>

namespace gcmp { class IModelView; }

namespace gnuf {

    class GnufModelViewItem;
    class QtBnufModelViewGroup;
    class QtBnufModelViewItem;
    class QtBnufUploadSelector;

    class GNUF_EXTENSION_EXPORT GnufModelViewGroup final
    {
        CANNOT_COPY_OR_ASSIGN(GnufModelViewGroup)
    public:
        GnufModelViewGroup(const std::wstring & caption);
        ~GnufModelViewGroup();

        const std::wstring & caption() const { return m_caption; }
        
        typedef std::list< gcmp::OwnerPtr< GnufModelViewItem > > Items;
        typedef std::vector< GnufModelViewItem *> RawItems;
        void addItem(gcmp::IModelView *, bool checkedInitially);
        const GnufModelViewGroup::Items & items() const { return m_items; }
        GnufModelViewGroup::RawItems rawItems();

        typedef std::list< gcmp::OwnerPtr< GnufModelViewGroup > > SubGroups;
        typedef std::vector< GnufModelViewGroup *> RawGroupItems;
        GnufModelViewGroup* addSubGroup(const std::wstring & caption);
        GnufModelViewGroup::RawGroupItems rawSubGroupItems();

        std::list<const gcmp::IModelView *> checkedModelViews() const;
        std::list<const gcmp::IModelView *> checkedAllModelViews() const;

        bool isChecked() const;
        void setChecked(bool);

        // Set if checked initially.
        enum class ECheckState:std::uint8_t
        { eUnchecked = 0, ePartiallyChecked = 1, eChecked = 2 };
        GnufModelViewGroup::ECheckState initialCheckState() const;
        GnufModelViewGroup::ECheckState GetCheckState() const;
    private:
        friend class QtBnufModelViewGroup;
        void    connectWith(QtBnufModelViewGroup *);
        void disconnectFrom(const QtBnufModelViewGroup * const);

        std::wstring m_caption;
        gcmp::WeakPtr<QtBnufModelViewGroup> m_qtImpl;
        GnufModelViewGroup::Items m_items;
        GnufModelViewGroup::SubGroups m_subGroups;
    };

    class GNUF_EXTENSION_EXPORT GnufModelViewItem final
    {
    public:
        GnufModelViewItem(gcmp::IModelView *, bool checkedInitially, GnufModelViewGroup *);
        ~GnufModelViewItem();

        gcmp::IModelView * modelView()  { return m_wpModelView.Get(); }
        const gcmp::IModelView * modelView() const { return m_wpModelView.Get(); }

        bool isCheckedInitially() const { return m_checkedInitially; }
        GnufModelViewGroup * group() const { return m_group; }

        const std::wstring & caption() const;

        bool isChecked() const;
        void setChecked(bool);

        bool operator<(const GnufModelViewItem &) const;
        
    private:
        friend class QtBnufModelViewItem;
        void    connectWith(QtBnufModelViewItem *);
        void disconnectFrom(const QtBnufModelViewItem * const);

        gcmp::WeakPtr<gcmp::IModelView>  m_wpModelView;
        const bool m_checkedInitially;
        GnufModelViewGroup * m_group;
        gcmp::WeakPtr<QtBnufModelViewItem> m_qtImpl;
    };

    class GNUF_EXTENSION_EXPORT GnufUploadSelector final
        : public IPalletEventHandler
    {
        CANNOT_COPY_OR_ASSIGN(GnufUploadSelector)
    public:
        explicit GnufUploadSelector(
            const std::wstring & title, 
            const std::wstring & banner,
            const std::wstring & warning);
        ~GnufUploadSelector();

        typedef std::list< gcmp::OwnerPtr< GnufModelViewGroup > > Groups;
        typedef std::vector< GnufModelViewGroup *> RawGroups;
        typedef std::list< std::pair< 
            gcmp::IModelView *,
            bool /* true:checked, false:unchecked */> > ModelViews;

        GnufModelViewGroup * addGroup(
            const std::wstring & caption,
            const GnufUploadSelector::ModelViews &);
        const GnufUploadSelector::Groups & groups() const { return m_groups; }
        GnufUploadSelector::RawGroups rawGroups();
        std::wstring getVersionAnnotation();
        // Show.
        enum EResultCode {
            eSubmit,
            eCancel
        };
        EResultCode show();

        /// \brief 添加子级
        /// \param pParentModelViewGroup 父节点
        /// \param caption caption 节点名称
        /// \param caption modelViews 模型视图
        GnufModelViewGroup * addSubGroup(GnufModelViewGroup* pParentModelViewGroup,
            const std::wstring & caption,
            const GnufUploadSelector::ModelViews & modelViews);
    protected:
        // Inherits from IPalletEventHandler...
        virtual void onHeaderButtonClicked(Pallet *) override;
        virtual bool onFooterButtonClicked(Pallet *) override;
        virtual bool onKeyEvent(Pallet *, IPalletEventHandler::EKey) override;

    private:
        GnufUploadSelector::Groups m_groups;
        gcmp::QtAutoPtr<QtBnufUploadSelector> m_qtSelector;
        const std::wstring m_title;
        GnufUploadSelector::EResultCode m_resultCode;
    };
}
